package com.github.fashionbrot;

import com.github.fashionbrot.algorithms.Algorithm;
import com.github.fashionbrot.common.util.ObjectUtil;
import com.github.fashionbrot.exception.AuthException;
import com.github.fashionbrot.exception.InvalidTokenException;
import com.github.fashionbrot.exception.SignatureVerificationException;
import com.github.fashionbrot.exception.TokenExpiredException;
import com.github.fashionbrot.function.TokenExceptionFunction;
import com.github.fashionbrot.util.AuthUtil;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

public class TokenMethod {

    public static TokenExceptionFunction tokenExceptionFunction = new TokenExceptionFunction() {
        @Override
        public void throwException(Exception exception) {
            if (exception instanceof InvalidTokenException) {
                AuthException.throwMsg("无效的token");
            } else if (exception instanceof SignatureVerificationException) {
                AuthException.throwMsg("token验证失败");
            } else if (exception instanceof TokenExpiredException) {
                AuthException.throwMsg("token已过期");
            }
        }
    };

    public static String getToken(HttpServletRequest request, String tokenName) {
        String token = request.getHeader(tokenName);
        if (ObjectUtil.isEmpty(token)) {
            // 如果请求头中没有，尝试从请求参数中获取
            token = request.getParameter(tokenName);
        }
        if (ObjectUtil.isEmpty(token)) {
            // 如果请求参数中没有，尝试从Cookie中获取
            Cookie[] cookies = request.getCookies();
            if (cookies != null) {
                for (Cookie cookie : cookies) {
                    if (tokenName.equals(cookie.getName())) {
                        token = cookie.getValue();
                        break;
                    }
                }
            }
        }
        return token;
    }


    public static <T extends AuthEncoder> T decrypt(Algorithm algorithm, Class<T> clazz, String tokenName) {
        return decrypt(algorithm, clazz, tokenName, tokenExceptionFunction);
    }


    public static <T extends AuthEncoder> T decrypt(Algorithm algorithm, Class<T> clazz, String tokenName, TokenExceptionFunction tokenExceptionFunction) {
        String token = "";
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (requestAttributes != null) {
            HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
            token = getToken(request, tokenName);
        }
        return AuthUtil.decrypt(algorithm, clazz, token, tokenExceptionFunction);
    }

    /**
     * 加密
     * @param algorithm 算法
     * @param encoder   加密对象
     * @return  token
     */
    public static String encrypt(Algorithm algorithm, AuthEncoder encoder){
        return AuthUtil.encrypt(algorithm, encoder);
    }

}
